﻿#include "sound.h"

_SoundManager smanager;

_SoundManager::_SoundManager()
{
	initialized = 0;
	to_play = 0;
	to_stop = 0;
	close_player = 1;
}

_SoundManager::~_SoundManager()
{
	if (initialized)
	{
		close_player = 0;
		engine->drop();
		buffers.clear();
		music_thread.join();
	}
}

void _SoundManager::Load(CL_ResourceManager &resources, CL_ResourceManager &m_resources)
{
	// Sounds
	engine = irrklang::createIrrKlangDevice();
	mengine = irrklang::createIrrKlangDevice();
	engine->setSoundVolume(global_state.master_vol);
	mengine->setSoundVolume(global_state.master_vol);
	std::vector<CL_String> resource_names = resources.get_resource_names_of_type("sample");
	for (size_t i = 0; i < resource_names.size(); i++)
	{
		CL_Resource t_sound = resources.get_resource(resource_names[i]);
		CL_VirtualDirectory dir = resources.get_directory(t_sound);
		CL_String path = t_sound.get_element().get_attribute("file");
		CL_IODevice file = dir.open_file_read(path);
		int size = file.get_size();
		cl_log_event("Debug", "Load %1 size = %2", path, size);
		sizes[resource_names[i].c_str()] = size;
		buffers[resource_names[i].c_str()] = new char[size];
		file.read(buffers[resource_names[i].c_str()], sizes[resource_names[i].c_str()]);
		sounds[resource_names[i].c_str()] = engine->addSoundSourceFromMemory(buffers[resource_names[i].c_str()], sizes[resource_names[i].c_str()], resource_names[i].c_str(), false);
		volumes[resource_names[i].c_str()] = CL_StringHelp::text_to_float(t_sound.get_element().get_attribute("volume").c_str());
		delays[resource_names[i].c_str()] = CL_System::get_time();
	}
	// Music
	std::vector<CL_String> m_names = m_resources.get_resource_names_of_type("track");
	CL_FileFactory* m_factory = 0;
	for (size_t i = 0; i < m_names.size(); i++)
	{
		CL_Resource t = m_resources.get_resource(m_names[i]);
		music_dir = m_resources.get_directory(t);
		if (!m_factory)
		{
			m_factory = new CL_FileFactory(music_dir);
			mengine->addFileFactory(m_factory);
		}
		tracks[m_names[i].c_str()] = mengine->addSoundSourceFromFile(t.get_element().get_attribute("file").c_str());
	}
	m_factory->drop();
	current_track = 0;
	current_music = 0;
	sound_delay = 70;
	music_thread.start(this, &_SoundManager::MusicPlayer);
	initialized = 1;
}

void _SoundManager::PlaySound(CL_String sname)
{
	if (sounds.find(sname.c_str()) != sounds.end())
	{
		if ((CL_System::get_time() - delays[sname.c_str()]) > sound_delay)
		{
			sounds[sname.c_str()]->setDefaultVolume(global_state.sfx_vol * volumes[sname.c_str()]);
			engine->play2D(sounds[sname.c_str()]);
			delays[sname.c_str()] = CL_System::get_time();
		}
	}
}

void _SoundManager::PlaySound_VolumeControl(CL_String sname, float vol)
{
	if (sounds.find(sname.c_str()) != sounds.end())
	{
		if ((CL_System::get_time() - delays[sname.c_str()]) > sound_delay)
		{
			sounds[sname.c_str()]->setDefaultVolume(global_state.sfx_vol * volumes[sname.c_str()] * vol);
			engine->play2D(sounds[sname.c_str()]);
			delays[sname.c_str()] = CL_System::get_time();
		}
	}
}

void _SoundManager::PlayMusic(CL_String sname)
{
	if (tracks.find(sname.c_str()) != tracks.end())
	{
		music_mutex.lock();
		track_to_play = sname;
		to_play = 1;
		music_mutex.unlock();
	}
}

void _SoundManager::StopMusic()
{
	stop_music_mutex.lock();
	to_stop = 1;
	stop_music_mutex.unlock();
}

int _SoundManager::GetMusicPosition()
{
	if (current_music)
		return current_music->getPlayPosition();
	else
		return 0;
}

void _SoundManager::UpdateMusicVolume()
{
	if (current_music)
		current_music->setVolume(global_state.music_vol);
}

void _SoundManager::MusicPlayer()
{
	cl_log_event("Debug", "Music player initialized");
	while (close_player)
	{
		if (to_stop)
		{
			stop_music_mutex.lock();
			to_stop = 0;
			stop_music_mutex.unlock();
			if (current_music)
				current_music->stop();
			current_music = 0;
		}
		else if (to_play)
		{
			music_mutex.lock();
			to_play = 0;
			CL_String song_to_play = track_to_play;
			music_mutex.unlock();
			current_track = tracks[song_to_play.c_str()];
			current_track->setDefaultVolume(1.0f);
			current_music = mengine->play2D(current_track, true, true);
			current_music->setVolume(global_state.music_vol);
			current_music->setIsPaused(false);
		}
		else
		{
			CL_System::sleep(500);
		}
	}
}
